/**
 * author      : dormi330
 * date        : 2018/6/26
 * project     : mybatis
 * description : 应用层服务
 */

package com.deep.trade.application.order;

import com.deep.trade.adaptor.required.sku.ItemSkuService;
import com.deep.trade.adaptor.required.sku.Sku;
import com.deep.trade.common.TradeException;
import com.deep.trade.domain.order.CommandPayOrder;
import com.deep.trade.domain.order.OrderQueryRepository;
import com.deep.trade.domain.order.OrderSummary;
import com.deep.trade.domain.order.TradeOrder;
import com.deep.trade.infrastructure.utils.CommonUtils;
import com.deep.trade.order.InDtoPayOrderSummary;
import com.deep.trade.order.InDtoPayTradeOrder;
import com.deep.trade.order.InDtoPaymentCalculate;
import com.deep.trade.order.SkuAndQty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class PayOrderService {

    @Autowired
    private CommandPayOrder commandPayOrder;

    @Autowired
    private ItemSkuService itemSkuService;

    @Autowired
    private OrderQueryRepository orderQueryRepository;

    private Logger logger = LoggerFactory.getLogger(this.getClass().getName());

    /**
     * 支付 OrderSummary
     *
     * @param inDtoPayOrderSummary
     */
    public void payOrderSummary(InDtoPayOrderSummary inDtoPayOrderSummary) throws Exception {
        logger.info("{}, {}", CommonUtils.currentClassAndMethod(), inDtoPayOrderSummary);

        if (null == inDtoPayOrderSummary) {
            throw new TradeException("arguments cannot be null");
        }

        String tenantCode = inDtoPayOrderSummary.getTenantCode();
        String orderSummaryId = inDtoPayOrderSummary.getOrderSummaryId();
        OrderSummary orderSummary = orderQueryRepository.orderSummaryOfId(tenantCode, orderSummaryId);
        if (null == orderSummary) {
            String errMsg = String.format("no such order, tenantCode=%s, orderSummaryId=%s", tenantCode, orderSummaryId);
            throw new TradeException(errMsg);
        }

        String payChannel = inDtoPayOrderSummary.getPayChannel();
        if (null == payChannel) throw new TradeException("payChannel cannot be null");

        String payType = inDtoPayOrderSummary.getPayType();
        if (null == payType) throw new TradeException("payType cannot be null");

        commandPayOrder.payOrderSummary(orderSummary, payChannel, payType);
    }

    /**
     * 支付 TradeOrder
     *
     * @param inDtoPayTradeOrder
     */
    public void payTradeOrder(InDtoPayTradeOrder inDtoPayTradeOrder) throws Exception {
        logger.info("{}, inDtoPayTradeOrder={}", CommonUtils.currentClassAndMethod(), inDtoPayTradeOrder);

        if (null == inDtoPayTradeOrder) throw new TradeException("arguments cannot be null");

        String tenantCode = inDtoPayTradeOrder.getTenantCode();
        String tradeOrderId = inDtoPayTradeOrder.getTradeOrderId();
        TradeOrder tradeOrder = orderQueryRepository.tradeOrderOfId(tenantCode, tradeOrderId);
        if (null == tradeOrder) {
            String errMsg = String.format("no such order, tenantCode=%s, tradeOrderId=%s", tenantCode, tradeOrderId);
            throw new TradeException(errMsg);
        }

        String payChannel = inDtoPayTradeOrder.getPayChannel();
        if (null == payChannel) throw new TradeException("payChannel cannot be null");

        String payType = inDtoPayTradeOrder.getPayType();
        if (null == payType) throw new TradeException("payType cannot be null");

        commandPayOrder.payTradeOrder(tradeOrder, payChannel, payType);
    }


    public BigDecimal calculatePayment(InDtoPaymentCalculate inDtoPaymentCalculate) throws Exception {
        logger.info("{}, inDtoPaymentCalculate={}", CommonUtils.currentClassAndMethod(), inDtoPaymentCalculate);
        if (null == inDtoPaymentCalculate) throw new TradeException("arguments cannot be null");

        List<SkuAndQty> skuAndQtyList = inDtoPaymentCalculate.getSkuAndQtyList();
        if (null == skuAndQtyList || skuAndQtyList.size() == 0) throw new TradeException("invalid sku and quantity");

        List<Sku> skuList = itemSkuService.skuOfIds(
                inDtoPaymentCalculate.getTenantCode(),
                skuAndQtyList
                        .stream()
                        .map(skuAndQty -> skuAndQty.getSkuId())
                        .collect(Collectors.toList()));

        final Map<String, BigDecimal> skuPriceMap = new HashMap<>();
        skuList.stream().forEach(sku -> {
            skuPriceMap.put(sku.getId(), sku.getPrice());
        });

        // 做简单计算

        BigDecimal total = BigDecimal.ZERO;
        for (SkuAndQty skuAndQty : skuAndQtyList) {
            BigDecimal price = skuPriceMap.get(skuAndQty.getSkuId());
            BigDecimal qty = new BigDecimal(skuAndQty.getQuantity());
            total = total.add(price.multiply(qty));
        }
        return total;
    }

}
